import {
  RequestConfig,
  RequestOptions,
  formatMessage,
  request,
} from '@umijs/max';
import { message, notification } from 'antd';
import { lang } from './lang';

interface ExtraParams {
  serialNumber?: string;
  userEmail?: string;
}
// 错误处理方案： 错误类型
enum ErrorShowType {
  SILENT = 0,
  WARN_MESSAGE = 1,
  ERROR_MESSAGE = 2,
  NOTIFICATION = 3,
  REDIRECT = 9,
}
// 与后端约定的响应数据格式
interface ResponseStructure {
  success: boolean;
  data: any;
  errorCode?: number;
  errorMessage?: string;
  showType?: ErrorShowType;
  msg?: string;
  code?: number;
}

// 运行时配置
export const requestConfig: RequestConfig = {
  // 统一的请求设定
  timeout: 60000,
  headers: { 'X-Requested-With': 'XMLHttpRequest' },
  withCredentials: true,

  // 错误处理： umi@3 的错误处理方案。
  errorConfig: {
    // 错误抛出
    errorThrower: (res: ResponseStructure) => {},
    // 错误接收及处理
    errorHandler: (error: any, opts: any) => {
      if (opts?.skipErrorHandler) throw error;
      if (opts.method === 'HEAD') {
        return;
      }
      // 我们的 errorThrower 抛出的错误。
      if (error.name === 'BizError') {
        const errorInfo: ResponseStructure | undefined = error.info;
        if (errorInfo) {
          const { errorMessage, errorCode } = errorInfo;
          switch (errorInfo.showType) {
            case ErrorShowType.SILENT:
              // do nothing
              break;
            case ErrorShowType.WARN_MESSAGE:
              message.open({
                key: errorMessage,
                type: 'warning',
                content: errorMessage,
              });
              break;
            case ErrorShowType.ERROR_MESSAGE:
              message.open({
                key: errorMessage,
                type: 'error',
                content: errorMessage,
              });
              break;
            case ErrorShowType.NOTIFICATION:
              notification.open({
                description: errorMessage,
                message: errorCode,
              });
              break;
            case ErrorShowType.REDIRECT:
              // TODO: redirect
              break;
            default:
              message.open({
                key: errorMessage,
                type: 'error',
                content: errorMessage,
              });
          }
        }
      } else if (error.response) {
        if (
          error.response.data?.success === false &&
          error.response.data?.msg
        ) {
          message.open({
            key: error.response.data.msg,
            type: 'error',
            content: error.response.data.msg,
          });
        } else {
          // Axios 的错误
          // 请求成功发出且服务器也响应了状态码，但状态代码超出了 2xx 的范围
          if (
            error.response?.status === 401 ||
            error.response?.status === 403
          ) {
            // 回到login
          } else if (error.response?.status === 0) {
            // 错误码为0，提示统一
            console.log(error);
            message.open({
              key: `Response status:${error.response.status}`,
              type: 'error',
              content: formatMessage({ id: 'request.fail' }),
            });
          } else {
            message.open({
              key: `Response status:${error.response.status}`,
              type: 'error',
              content: `Response status:${error.response.status}`,
            });
          }
        }
      } else if (error.request) {
        // 请求已经成功发起，但没有收到响应
        // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例，
        // 而在node.js中是 http.ClientRequest 的实例
        message.open({
          key: 'None response! Please retry.',
          type: 'error',
          content: 'None response! Please retry.',
        });
      } else {
        // console.log("Error", error);
        // 发送请求时出了点问题
        message.open({
          key: 'Request error, please retry.',
          type: 'error',
          content: 'Request error, please retry.',
        });
      }
    },
  },

  // 请求拦截器
  requestInterceptors: [
    async (config: RequestOptions) => {
      // 请求之前 如果token过期尝试刷新一次token , 刷失败也不抛错
      // 拦截请求配置，进行个性化处理。
      const headers = {
        ...config.headers,
        ...getHttpHeaders(),
      };
      return { ...config, headers };
    },
  ],

  // 响应拦截器
  responseInterceptors: [
    [
      (response: any) => {
        const { headerAuthorization } = response.data;
        const { authorization } = response.headers;
        if (headerAuthorization === 'authorization') {
          sessionStorage.setItem('access_token', `Bearer ${authorization}`);
        }
        return response;
      },
      (error: any) => {
        const { response } = error;
        const originalRequest = error?.config;
        // return Promise.resolve(response);
        // 重试1次 超出直接跳登录去吧
        if (
          (response?.status === 401 || response?.status === 403) &&
          originalRequest?.retryCount !== 1
        ) {
          const promise = async (resolve: any, reject: any) => {
            try {
              const res = await request(originalRequest.url, {
                ...originalRequest,
                getResponse: true,
                retryCount: 1,
              });
              resolve(res);
            } catch (error) {
              reject(error);
            }
          };
          return new Promise(promise);
        }
        return Promise.reject(error);
      },
    ],
  ],
};

export const getHttpHeaders = () => {
  return {
    // auth授权头信息
    Authorization: sessionStorage.getItem('access_token'),
    Language: lang.getLocale(),
    code: sessionStorage.getItem('code') ?? '',
    TimezoneOffset: new Date().getTimezoneOffset(),
  };
};
